home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / PROGRAMM / DB_CLIPP / 0669.ZIP / DB3TAW.TXT < prev    next >
Text File  |  1985-11-30  |  47KB  |  1,070 lines

  1. dBASE III notes .001               Thomas A. Wells
  2.                                    146 D Street SE
  3. See BBS @ 321-7441                 Washington, DC 20003
  4.   for other notes.                 (202)546-3409
  5.  
  6.      I am providing a weekly series of these notes covering my
  7. experiences as a dBASEIII programmer.  I work as a consultant and
  8. presently am spending 40+ hours per week writing programs and managing
  9. databases using primarily dBASEIII.
  10.      This week's experience covers an odd occurrence.  While
  11. interactively programming along, debugging a command file for
  12. displaying numbers of items, their record numbers and certain fields,
  13. the computer displayed the error message "File is already open".  From
  14. my copy of the "PRODUCT USAGE REPORT" from A-T (see below), I found
  15. that this message should apply only if I tried to use a command file
  16. (.PRG) to call itself, which I wasn't!
  17.      There followed an hour of trying to decide what was wrong,
  18. changing EXIT statement locations in various DO WHILE loops both in the
  19. main and sub-programs, and trying to figure out why the call had worked
  20. twice immediately before the error message appeared, etc.  Finally it
  21. was time to call the A-T help line - (213)558-0086 (have your dBASE III
  22. serial number handy!).
  23.      After some "Have you tried..." and "Yes, I have, but what
  24. about..." iterations, I was told to boot up the backup copy of the .EXE
  25. programs.  Since I'm using a PC-XT, I put the disk in drive A, typed
  26. A:DBASE and lo!  Everything worked!  The final fix for the problem was
  27. to recopy the .EXE programs back to the hard disk from the original
  28. system disk with COPY *.EXE C:.
  29.      Why did this work?  I'm not sure, but it appears that the copy of
  30. the programs on the hard disk became corrupted, possibly in the stack
  31. management area.  So far, after another week's run, no further problems
  32. have occurred.  I'm not suggesting this as a fix for all programming
  33. problems, but if you're sure(?) of everything else, give it a try.  The
  34. experience leaves me a little less sure of the integrity of either
  35. dBASEIII or IBM's hard disk.  My backups have been more frequent
  36. lately.
  37.      The PRODUCT USAGE REPORT mentioned above has been very helpful.
  38. I was sent it on request through the Technical Assistance phone number
  39. listed above.
  40.      The last 10 pages or so list all the dBASEIII error messages and
  41. their meanings - very helpful to the programmer and, of course, left
  42. out of the original manual. The first half of the document consists of
  43. further tips, elucidations and comments regarding installation,
  44. programming usage of the various commands, and sections on the
  45. dCONVERT and dFORMAT utilities.  I don't know whether the report is to
  46. be issued monthly or what - mine is dated October 1, 1984.  If you're
  47. seriously programming with dBASEIII, get one!
  48.      As a final thought for this week, using Wordstar with the program
  49. has been easy and helpful.  Linking the two programs requires nothing
  50. more than creating a CONFIG.DB file with the statements WP=WS and
  51. TEDIT=WS in it.  Be sure and run the Wordstar INSTALL program on the
  52. version you want to use before you do, so it will come up running in
  53. the non-document mode (menu E, letter C does the trick).
  54. - - - - -
  55.  
  56. dBASE III notes .002
  57.  
  58.      When adding records to a file, I sometimes like to stop and press
  59. F4, the function key that is programmed as "dir;".  This gives a
  60. listing of the .DBF files only from within dBASEIII.  The first time I
  61. did this, the file I just added a record to did not show the additional
  62. record!  That is, the number of records was 89 prior to adding one and
  63. still showed 89 after the DIR command.
  64.      The answer is relatively simple -- the directory does not appear
  65. to be updated as records are added -- a command to close the file seems
  66. to be required first, such as CLEAR ALL or CLOSE DATABASES.  To see how
  67. many records have been added, issue the command CLEAR ALL (or
  68. equivalent), then DIR.
  69.      Of course, there are many other ways to determine how many records
  70. a file has while in dBASEIII -- also true of nearly every way of doing
  71. almost anything.  One could type GO BOTTOM, then ?RECNO().  Or if you
  72. had just added a record, ?RECNO() would work with out the GO BOTTOM.
  73.     This week's puzzler happened while trying to index a .DBF file
  74. where the first index key was a string (character) variable, and the
  75. second key was a numeric variable.  According to the rules, the numeric
  76. variable must be converted to a string via the STR() function, since
  77. multiple indexing keys must all be strings.  So I did the conversion.
  78. Right in the INDEX command:
  79.  
  80. INDEX ON string_var + STR(numeric_var) TO indexfile
  81.  
  82. The result was puzzling, to say the least.  Examination of the file
  83. using the EDIT command showed it to be in ascending order, as
  84. advertised, with respect to the string_var, but in descending order
  85. with respect to the numeric_var!  Not what I wanted at all.
  86.      The conversion to a string should not have affected order of the
  87. sort, since the numeric_var was less than 10 (single digit), and the
  88. string representation appeared to have the same number of leading
  89. blanks for each number.  Also, the ASCII value of "2" is higher than
  90. that for "1", so the blanks should not have upset the order.
  91.      The cure?  Change the field definition to "character".  Then, the
  92. indexing command becomes:
  93.  
  94. INDEX ON string_var1 + string_var2 TO indexfile
  95.  
  96. Examination of the ordering of the file then showed it to be organized
  97. in ascending order with respect to both keys.
  98. - - - - -
  99.  
  100. dBASEIII notes .003
  101.  
  102.      This week's dBASE III tip is for the CONFIG.DB file with thoughts
  103. about making screen displays easier to read and maybe a little fancier
  104. with bold, underline and graphics.
  105.  
  106. CONFIG.DB...
  107.      is a file that dBASEIII looks for after you type "DBASE".  It may
  108. be used for many different purposes including tieing in a word
  109. processor other than the built-in one, setting most of the SET
  110. parameters and setting the function keys.
  111.      Let's see how it is used to set the function keys.  First, note
  112. that once again the manual (p. 1-126) is incorrect.  There, we are told
  113. to include statements like:  F2 = 'CLEAR;'  to set the function keys.
  114. Not so!  If you try this, an error message will greet you, and the key
  115. will not be set.
  116.      The method used to set the function keys is:  F2 = CLEAR;
  117. Notice that no quotation marks are used.
  118.      Although it is not mentioned, there is a limit to the number of
  119. characters that a function key can represent.  I don't know exactly
  120. what it is, but if you try to set one key to:
  121.  
  122. F2 = SET PRINT OFF; SET DEVICE TO SCREEN;
  123.  
  124. you will find that the letters at the end, say, "EEN;", have "wrapped"
  125. onto F3.  To make the above workable, use the following statement:
  126.  
  127. F2 = SET PRIN OFF;SET DEVI TO SCREE;
  128.  
  129. Note the use of the 4-letter abbreviations for the commands, and that
  130. no blank is used after the first ";".  Here's an example of a CONFIG.DB
  131. file using the above information:
  132.  
  133. WP = WSN
  134. TEDIT = WSN
  135. F2 = clea all;
  136. F3 = modi comm
  137. F4 = set prin off;set devi to scre;
  138.  
  139.      As described in an earlier note, the first two statements link
  140. WORDSTAR (INSTALLed in the non-document mode) to the MEMO field editing
  141. and the MODIFY command editing.  The last three statements set the
  142. function keys as described above.
  143.      The only invisible trick is that for the F3 key there is a blank
  144. after the word "comm " so that all I need to do after pressing the F3
  145. key is to type the name of the command file I wish to edit and press
  146. enter.
  147.      The possibilities for using this feature are limited only by the
  148. programmer's imagination.  If you use this feature for the final end-
  149. user program remember that you're really trying to make life simpler
  150. for them.
  151.  
  152. GRAPHICS...
  153.      are not too hard to do with dBASEIII.  It will, however, take some
  154. patience and trial-and-error...
  155.      My system is a PC-XT with the Hercules graphics board and the IBM
  156. mono monitor.  I say this because the results of the statements
  157. outlined below will surely be different if you use other hardware.
  158.      It all started with a desire to make a full screen look better,
  159. and also to make the important items stand out.
  160.      First, DFORMAT was used to draw nice boxes on the screens where
  161. they would help make things clearer.  Using DFORMAT, if anyone's
  162. interested, could be the subject of some entire later notes - it's
  163. truly an arcane challenge!
  164.      After the boxes were drawn, and the .FMT file was generated, I
  165. naturally wanted to change something.  Go back to DFORMAT?  No way.  It
  166. might be made to edit an existing file, but I'm over 40 and may not
  167. have enough time left to figure out how.  So how to make changes to the
  168. graphics?
  169.      All the ASCII equivalent characters from the BASIC manual - that's
  170. how! dBASEIII will happily put any character on the screen that is on
  171. that list, so there is a copy of it hanging on the wall next to my
  172. computer.  To put a segment of a vertical double line on the screen,
  173. just enter:  ? CHR(186)  And there it is.  Of course, @ SAY may also
  174. be used.
  175.  
  176. BOLDFACE and UNDERLINE...
  177.      are somewhat more involved, but easy once you get the idea.  If
  178. the SET COLOR command is properly used for your hardware, all kinds of
  179. emphasis is possible.  For you color monitor users, more experimenting
  180. will be needed. The challenge with a color monitor is not to overdo it.
  181. Here's the trick.  For my hardware (above) typing:
  182.  
  183. SET COLOR TO U1/0,0/7,0
  184.  
  185. results in everything being underlined.  Note that the second parameter
  186. 0/7 leaves the @ SAY/GET reversed fields alone.  Read the manual to see
  187. what is affected by each quantity between the parentheses - it's not
  188. ALWAYS wrong.
  189.      Well there is one thing wrong - or at least it "works funny" for
  190. me.  The underline is supposed to be turned on by the "U". On my
  191. computer, the "1" turns on the underline - the "U" can be omitted.
  192.      To see how this can be put to use in a command file, here's one
  193. way to do it.  Build a .MEM file by setting the values of "b", "bu",
  194. "u" and "off" as shown:
  195.  
  196. Variable        Value
  197.    u        "SET COLOR TO U1/0,0/7,0"
  198.    off        "SET COLOR TO  7/0,0/7,0"
  199.    bu        "SET COLOR TO +1/0,0/7,0"
  200.    b        "SET COLOR TO +7/0,0/7,0"
  201.  
  202.      After setting the values shown, type [SAVE TO color] [enter].
  203. Then later in a command file use the RESTORE FROM color statement to
  204. activate the variables in memory.  Don't forget the ADDITIVE modifier
  205. if other variables are active.
  206.      "off" represents the default settings; I think they're same as
  207. when dBASEIII is first started.
  208.      "u" produces underline, "bu" produces both boldface and underline,
  209. and "b" produces boldface - all on the screen of course.
  210.      Then in a command file, or even from the dot prompt, type [&b]
  211. [enter] and everything from then 'til the [&off] occurs will be in
  212. boldface.
  213.      The underline is slightly different.  If you type [&u] [enter],
  214. every line on the screen will suddenly be underlined!  Don't worry -
  215. if the command is issued in a printed line somewhere, it'll only
  216. underline where you tell it to.
  217. - - - - -
  218.  
  219. dBASE  III notes .004                  December    19, 1984
  220.  
  221. This week - a newsflash, a correction and a print hint:
  222.  
  223. NEWSFLASH
  224.     Yesterday an update announcement from A-T arrived.  The offer was
  225. to upgrade to dBASE III version 1.1!  The details are that for $25 you
  226. get the "improved" version which will run on the PC-AT as well as the
  227. PC & XT, and can be "completely installed on any hard-disk IBM PC/XT,
  228. AT or 100% IBM PC compatible system".  The brochure is understandably
  229. silent as to whether or not any of the bugs found by users and/or
  230. mentioned in their "Product Usage Re port" were fixed.  My check is in
  231. the mail.
  232.     My reaction to this is that since the program has been on the
  233. market less than 6 months, a charge for an update is an insult. Is
  234. this tactic of charging for each item separately an imitation of
  235. IBM?  (If the bugs are reduced, maybe it'll be worth it.  How about
  236. buyers who get version 1.0 this week?  Will they get a "free" upgrade?
  237. If you know anyone about to invest in dBASE III, make sure they get the
  238. word.  Surely all the present store stock hasn't been revised to
  239. version 1.1 yet.)
  240.  
  241. CORRECTION
  242.     Last note said there is no stated limit on the length of the SET
  243. FUNCTION command.  My face is red - right there on page 4-113 of the
  244. manual it says 30 characters.
  245.  
  246. PRINT HINT
  247.     In formatting printouts to either/both the screen and printer it
  248. is useful to be able to embed a number inside text.  For example, you
  249. may want to print:  "There are 12 items in this list."
  250.     In printing them or using @ SAY, the numbers will be preceded
  251. by up to 7 blank spaces.  In the above example if we issued these
  252. commands:
  253.  
  254. ? "There are"
  255.   ?? n
  256.   ?? "items in this list."
  257.  
  258. The result would be:  There are 12items in this list.
  259.     Note that there are 6 blanks in front of the number and none after
  260. it.  There doesn't appear to be any simple way to eliminate the extra
  261. blanks in front of the number.  Adding one to the end is simple.  If
  262. you know how long the number will be, say always 2 digits, the answer
  263. is simple.  Just convert the number to a string and use the STR()
  264. function to print only the rightmost 2 characters.  But what if the
  265. number of digits varies?  Here is one way to handle that problem:
  266.  
  267. ? "There are "
  268.   ?? STR(n,(LOG(n+.5)/LOG(10)+1))
  269.   ?? " items in this list."
  270.  
  271. Since there doesn't seem to be any easy way within dBASE III to tell
  272. how many digits a number has, the formula above takes your number, n,
  273. and uses the LOG() function to do the job, then the STR() function to
  274. print the exact number you wanted.
  275.     The addition of the .5 to the number n is to overcome any internal
  276. inaccuracies in the LOG() function's number representation.  The result
  277. then is:  There are 12 items in this list.
  278. - - - - -
  279.  
  280. dBASE III notes .005                  January 15, 1984
  281.  
  282.      This note deals with "!", "@" and "?". "!" is a very handy tool
  283. for the dBASE III programmer.  It runs any system level program for you
  284. from within dBASE either from the dot prompt or from within a command
  285. file.  It can be found in the manual under the equivalent syntax of
  286. "RUN".
  287.      For example, I got tired of typing COPY *.dbf a:, etc. at the end
  288. of every session to back up all the files that may have changed, and
  289. besides that, the end user won't want to or maybe even won't know how
  290. to.  So here's a backup routine that will back up all the files, with a
  291. built-in safety factor.  If the operator puts in the wrong disk, an
  292. opportunity is given to swap it through the use of the FILE command.
  293. Here it is:
  294.  
  295. *********************** BACKUP.PRG **************************
  296. *  Backs up .DBF, .MEM and .NDX files for the operator.     *
  297. *  An "invisible command" accessed by pressing "P" is       *
  298. *  included to back up .PRG and .FMT files.  This program   *
  299. *  checks to see whether the proper disk is put in drive A  *
  300. *  and gives a chance to abort before the copying begins.   *
  301. *************************************************************
  302.  
  303. CLEAR ALL
  304. CLEAR
  305. SET TALK OFF
  306.  
  307. @ 10,10 SAY "Insert the backup disk into Drive A."
  308. @ 12,10 SAY 'Press "B" to begin, "A" to abort'
  309. WAIT SPACE(21) to j
  310. j = UPPER(j)
  311.  
  312. * Turn the VERIFY function of DOS ON
  313. ! VERIFY ON
  314.  
  315. DO CASE j
  316.   CASE j = "B"
  317.     * Check to see if correct backup disk is in drive A:
  318.     IF FILE ("A:filename.DBF")
  319.       SET CONSOLE OFF
  320.       * Copy all the database & related files
  321.       !COPY *.DBF A:
  322.       !COPY *.MEM A:
  323.       !COPY *.NDX A:
  324.       SET CONSOLE ON
  325.     ELSE
  326.       * Argue if the disk isn't recognized...
  327.       @ 12,10 CLEAR
  328.       * Turn the bright letters on (see earlier note)
  329.       &b
  330.       @ 12,10 SAY 'This disk may not be the correct one!'
  331.       &off
  332.       @ 14,10 SAY 'When the correct one is inserted, press "B"'
  333.       @ 16,10 SAY 'To Abort, press "A"'
  334.       WAIT SPACE(31) TO b
  335.       b = UPPER(b)
  336.       DO CASE b
  337.      CASE b = "B"
  338.        SET CONSOLE OFF
  339.        !COPY *.DBF A:
  340.        !COPY *.MEM A:
  341.        !COPY *.NDX A:
  342.        SET CONSOLE ON
  343.      CASE b = "A"
  344.        RETURN
  345.       ENDCASE b
  346.    CASE j = "A"
  347.       RETURN
  348.    * This choice backs up the program and format files
  349.    CASE j = "P" .AND. FILE('A:filename.PRG')
  350.        !COPY *.PRG A:
  351.        !COPY *.FMT A:
  352. ENDCASE j
  353.  
  354. SET TALK ON
  355. SET CONSOLE ON
  356. !VERIFY OFF
  357. RETURN
  358.  
  359.      If your program files or database files are changed often, this
  360. program saves a lot of work.  The other possibilities for using "!" (or
  361. "RUN", if you must) are intriguing.  How about a communications program
  362. or another DOS function or ... ?
  363.      "@" and "?" can both be used to print reports, among other things.
  364.      "?" is preceded by a linefeed and a carriage return <CR>, while
  365. "??" is not.  Together these two can be used to print many parts of any
  366. report, such as headings.
  367.      Where formatted fields such as telephone numbers, dates or dollar
  368. amounts are to be printed, the PICTURE clause is handy, and "@" is
  369. probably easier to use.
  370.      To have the output of both "?" and "@" routed to the printer, it
  371. is probably safer to use:
  372.  
  373. SET PRINT ON
  374. SET DEVICE TO PRINT
  375.  
  376. Then anything that either "@ SAY" or "?" does is done by the printer
  377. and not the console screen.  "@ GET" is ignored.
  378.      Watch out for putting the "@" commands into a sequence that causes
  379. the printer to back up either a line or space(s) on a line.  You may
  380. get an unwanted EJECT by the printer.  Here's an example of the use of
  381. a mixture of these commands:
  382.  
  383. * Printer codes
  384. bold_on = CHR(27) + CHR(88) + CHR(49)
  385. bold_off = CHR(27) + CHR(88) + CHR(48)
  386.  
  387. ? bold_on
  388.   ?? heading
  389.   ?? SPACE(20) + DTOC(DATE())
  390.   ?
  391.   ? bold_off
  392.    @ PROW(),0 SAY id_number PICTURE "@R 99-(999)-99"
  393.    @ PROW(),PCOL()+2 SAY id_number_2 PICTURE "@R 99/999/A"
  394.    @ PROW(),PCOL()+2 SAY SUBSTR(var1,1,14)
  395.    @ PROW(),PCOL()+2 SAY var2 + ". " + var3
  396.    @ PROW(),PCOL()+2 SAY SUBSTR(var4,1,1) + ". " + var5
  397.    @ PROW(),PCOL() SAY RECNO()
  398.    ?
  399.  
  400.      In the example the variables bold_on and bold_off are printer
  401. control codes covered in an earlier note, if memory serves. PROW()
  402. keeps the cursor on the same line.  PCOL()+n spaces the data to match
  403. the heading.  Either "?" or "@" could have been used to print var1 -
  404. var5 and RECNO().  The final "?" is to move the cursor to the beginning
  405. of the next line.  Without it, any subsequent output will start at the
  406. end of RECNO().  Instead of PCOL() +n, a number may be used to select
  407. the starting column for the next item.  @ PROW(),100 will place the
  408. first character in column 100 (just be sure your printer can
  409. accommodate column 100).  Place your collection of "?" and "@"
  410. statements inside one or more DO WHILE loops and you're set to go.
  411. - - - - -
  412.  
  413. dBASE III notes .006                         January 24, 1984
  414.  
  415. Version 1.1 has arrived. Comments this time are about v1.1:
  416. Installation, Autostart, dFORMAT/SED, and "Oops".
  417.  
  418. INSTALLATION
  419.      Installation looks difficult, but is easy.  The trick is to follow
  420. the directions.  The bottom line is that yet another protection scheme
  421. is used, this time to allow hard disk users to boot directly from the
  422. hard disk without the system disk having to be in drive A:.  To unravel
  423. the directions, you are apparently allowed one copy on the hard disk
  424. per system disk.  The intent is that if you want to move the software
  425. to another machine you must "uninstall" the copy (put it back onto the
  426. system disk), then move the program to your other machine.  Ridiculous.
  427. Even more ridiculous is A-T's statement that you may want to
  428. "uninstall" the program if "your hard disk becomes damaged"!  They
  429. don't tell how to do this wonderful magic feat.
  430.      I'm opposed to copy protection.  There are already several small
  431. programs available for unprotecting dBASE III v1.0; those for v1.1
  432. will be soon.
  433.  
  434. AUTOSTART
  435.      It is now practical (and legal) to boot your database from the
  436. hard disk using a combination of the AUTOEXEC.BAT and CONFIG. DB files.
  437. Here's how.  The AUTOEXEC.BAT file has as its last two statements:
  438.  
  439. CD\DBMS\DB3
  440. dbase
  441.  
  442. The first statement changes the default directory to the dBASE III
  443. directory and the last invokes the program.  Since v1.1 requires no
  444. boot disk in drive A:, it comes alive and looks for a CONFIG.DB file.
  445. Mine ends with:
  446.  
  447. COMMAND = DO mainmenu
  448.  
  449. The result of these two additions to these files means that I can walk
  450. up to the computer, flip on the main switch and walk away.  In about
  451. two minutes (using a 640K XT), the main menu is on the screen waiting
  452. for my use without ever pressing a key.  See page 1-126 in the manual
  453. for a little more about CONFIG.DB and an example of COMMAND.
  454.  
  455.  
  456. dFORMAT/SED
  457.      What was dFORMAT in v1.0 is SED in v1.1.  The new version looks
  458. the same as the old, but it's a different size so maybe some of the
  459. bugs have been fixed.  I liked dFORMAT so I plan to like SED.  It is a
  460. good time-saver for creating screens for input and output.  You can
  461. even use fancy boxes!  Try it - the on-line help is good.
  462.  
  463. OOPS
  464.      After one day with v1.1, a bug appeared.  Or maybe I should call
  465. it a correction to the bug. With v1.0, printing a date to the screen
  466. with @ SAY required a PICTURE clause like "@R 99/99/ 99" to get it to
  467. look like a date.  On the printer, you didn't need it, which agreed
  468. with the manual (see page 4-20).  That was one page that never made
  469. itself clear to me, except it encouraged me into some trial/error that
  470. resulted in my not using any PICTURE clauses with date variables
  471. except, as noted above, on the screen.  If you happen to have a good
  472. explanation of page 4-20, please send it right away.
  473.      Now v1.1 works the same as the printer.  No PICTURE clauses needed
  474. on the screen.  Is that clear from the documentation?  No.
  475.  
  476.      Documentation for v1.1?  Here's the total:
  477.           Installation - 5 pages
  478.           Corrections - 4 pages (scattered items)
  479.           New pages - 1
  480.           SED comments - 4
  481.      It might be a good idea to funnel all the new and/or old bugs for
  482. dBASE III, particularly v1.1, to one person.  The idea is to accumulate
  483. them and forward to users groups and A-T.
  484. - - - - -
  485.  
  486. dBASE III notes .007                         April 4, 1985
  487.  
  488.      Today's a good day for some thoughts about screen and printer
  489. graphics.  I use Wordstar for all my dBASE III programming.  As a
  490. result, graphics are fairly simple to do, as I hope you'll see shortly.
  491. If you use Sidekick, or the dBASE III editor, or some other word
  492. processor the principles may or may not apply.
  493.      The first problem is to get the graphics characters into the
  494. editor; that is, to make them available on the screen.  I did it by
  495. using dFORMAT, supplied with v1.0. The "new" screen-making tool, SED,
  496. supplied with v1.1 will make you work harder for the same result.  Or
  497. less.  The process for getting control of lines and boxes is:
  498.      1. Draw a box any way you can in either SED or dFORMAT.
  499.         (Or any other way - all's fair.)
  500.      2. Use SED or dFORMAT to generate the .PRG file.
  501.         (Or see above parentheses)
  502.      3. Import the .PRG file into your word processor.
  503.      4. Use your word processor's functions for copying, moving
  504.         and editing to construct other figures as needed.
  505.      If you have dFORMAT, you can generate a box completely and import
  506. the whole thing into your word processor.  If you're "stuck" with SED,
  507. it's a little more arcane.
  508.      Here's a short list of keys and their effect on the screen for
  509. those with SED:
  510.     Key    CHR()        Key    CHR()
  511.     F1    187        F2    200
  512.     F3    189        F4    190
  513.     F5    191        F6    192
  514. And so on.  Refer to your BASIC manual for the figures represented by
  515. the ASCII codes.
  516.      With SED, if you use the SHIFT, ALT and CONTROL keys with the
  517. function keys (and even the backslash key) you can get some of the PC
  518. graphics & other special characters, but it's almost too time
  519. consuming.  Besides, after all that I still wasn't able to make a
  520. complete box!  The vertical line character managed to escape me
  521. completely.  So I went back to dFORMAT, got both the single and double
  522. line samples, and started from there.
  523.      As another possibility, I used Wordstar in the non-document mode
  524. to write this note, so the example below may be used, if you can ingest
  525. it with your dBASE III editor.  Here's a sample box:
  526.  
  527. @ 2,0 SAY "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM"
  528. @ 2,55 SAY "MMMMMMMMMMMMMMMMMMMMMMM;"
  529. @ 3,0 SAY ":"
  530. @ 3,78 SAY ":"
  531. @ 4,0 SAY ":"
  532. @ 4,14 SAY "Whatever the TITLE of this here screen is..."
  533. @ 4,78 SAY ":"
  534. @ 5,0 SAY ":"
  535. @ 5,78 SAY ":"
  536. @ 6,0 SAY ":"
  537. @ 6,78 SAY ":"
  538. @ 7,0 SAY ":"
  539. @ 7,20 SAY "und so weiter..."
  540. @ 7,78 SAY ":"
  541. @ 8,0 SAY ':'
  542. @ 8,78 SAY ":"
  543. @ 9,0 SAY ":"
  544. @ 9,55 SAY ':'
  545. @ 10,0 SAY ":"
  546. @ 10,55 SAY ":"
  547. @ 11,0 SAY ":"
  548. @ 11,55 SAY ":"
  549. @ 12,0 SAY ":"
  550. @ 12,55 SAY ":"
  551. @ 13,0 SAY ":"
  552. @ 13,78 SAY ":"
  553. @ 14,0 SAY ":"
  554. @ 14,55 SAY ":"
  555. @ 15,0 SAY ":"
  556. @ 15,78 SAY ":"
  557. @ 16,0 SAY ":"
  558. @ 16,78 SAY ":"
  559. @ 17,0 SAY ":"
  560. @ 17,78 SAY ":"
  561. @ 18,0 SAY ":"
  562. @ 18,78 SAY ":"
  563. @ 19,0 SAY ":"
  564. @ 19,78 SAY ":"
  565. @ 20,0 SAY ":"
  566. @ 20,78 SAY ":"
  567. @ 21,0 SAY ":"
  568. @ 21,78 SAY ":"
  569. @ 22,0 SAY ":"
  570. @ 22,78 SAY ":"
  571. @ 23,0 SAY "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM"
  572. @ 23,55 SAY "MMMMMMMMMMMMMMMMMMMMMMM<"
  573.  
  574.      The above code should, if you insert it in a .PRG or a .FMT file,
  575. produce a complete box on your screen or printer consisting of gen -
  576. yoo - wine PC graphics characters.
  577.      If you drag this code (or the whole note) into your word
  578. processor, you may see only colons (:), H's (H), M's (M), semicolons
  579. (;), I's (I) and a less than sign (<).  Don't be fooled; this is the
  580. way the graphics are displayed by Wordstar.
  581.      Don't erase one of the "graphics" colons and then try to replace
  582. it with a colon from your keyboard - life don't work that way.  The
  583. ASCII codes for the "real" colon and the "graphics" colon are quite
  584. different. By about 128...
  585.      If you're still here, and have got this figure or an equivalent
  586. one into your word processor, you're ready for step 4.  Move, copy and
  587. delete until you (think you) have reformed the size and shape of your
  588. box to suit your need.  Then run (DO) the program.  Chase the bugs
  589. until you get it right, and spruce up all your screens.  As a side
  590. note, you can also "DO" a .FMT file!
  591.      Also note that if you have a PC "compatible" printer, both single
  592. and double line graphics will print, though most printers print either
  593. as only a single line.
  594. - - - - -
  595.  
  596. dBASE III notes .008                         April 11, 1985
  597.  
  598. PEEK...
  599.      is not documented, but a dBASE programmer can have some fun with
  600. it and perhaps learn a little about programming and screen handling in
  601. the process.  So purists are excused from reading the following example
  602. program:
  603.  
  604. ********  PEEK.PRG
  605. * Prints the location, value & CHR() where possible
  606. * OK up to location 32767 - modify for higher locations
  607.  
  608. CLEAR
  609. INPUT "begin at ?" to begin
  610. INPUT "how many ?" to num
  611.  
  612. loc = begin
  613. r = 4
  614. c = 0
  615.  
  616. DO WHILE loc < begin + num
  617.  
  618.    * trim location number & put in proper location on screen
  619.    * see earlier note for trim technique involving logs
  620.    @ r,c*25 SAY STR(loc,(LOG(loc+.5)/LOG(10)+1))
  621.    pk = PEEK(loc)
  622.  
  623.    * take care of "unprintable" characters
  624.    IF pk > 31 .AND. pk <255
  625.       @ ROW(),COL() SAY " CHR("+STR(pk,3)+ ") = "+CHR(pk)
  626.    ELSE
  627.       IF pk <> 0
  628.           @ ROW(),COL() SAY " CHR("+STR(pk,3) + ")"
  629.       ELSE
  630.           @ ROW(),COL() SAY " CHR(  0)"
  631.       ENDIF
  632.    ENDIF
  633.  
  634.    loc = loc + 1
  635.  
  636.    * print downward on screen
  637.    r = r + 1
  638.  
  639.    * don't go off the bottom of the screen
  640.    IF r > 22
  641.       r = 4
  642.       c = c + 1
  643.  
  644. * don't go off the right of the screen
  645.          IF c > 2
  646.             c = 0
  647.             WAIT
  648.             @ 4,0 CLEAR
  649.          ENDIF
  650.    ENDIF
  651. ENDDO
  652.  
  653. * don't overwrite data on the screen when finished
  654. @ 23,0 SAY ""
  655.  
  656.      If you trim the above program out of this note and run it, you
  657. will see:
  658.    - a request for the locations you want printed on the screen
  659.    - a request for the number of locations after the start above
  660.    - columns of data printed
  661. The programming techniques used are:
  662.    - printing in columns because they're easier to read than rows
  663.    - showing the ASCII representation where possible
  664.    - managing to stay on the screen, avoiding errors
  665.      There are two challenges here I'd like to offer.  First, see if
  666. you can make the program work above location 32767.  Second, with the
  667. start given, write a disassembler!  At least for the memory locations
  668. below 32768; you could use a .dbf to store the op-codes and the
  669. associated decimal & hex values.  Silly?  Maybe not, if you consider
  670. it a way to learn.
  671.  
  672. INDEXING...
  673.      can be very helpful for quick access to data in any order, and is
  674. necessary for certain other commands such as SEEK, FIND, SET INDEX and
  675.  
  676. SET RELATION.
  677.      Once a file is INDEXed, it is important to back up the .ndx file
  678. whenever the .dbf file is backed up.  If you don't back it up, loss of
  679. a disk will mean reconstructing the .ndx file.  If you know what the
  680. index key fields were either from experience or documentation then
  681. rebuilding the index file is only time consuming.  If you don't know
  682. what the key fields were, your problem could be quite substantial.
  683.      One way to avoid the problem is to keep track of the .ndx file
  684. keys.  Here's one way to do it:
  685.      Back up your .ndx files along with the associated .dbf files.
  686. A suggested "easy" way to do this is contained in an earlier note.
  687.      Then keep printed copies of your file structures handy by issuing
  688. the command "LIST STRUCTURE TO PRINT" every time you modify the file's
  689. structure.  Then after each time you create an index file for the .dbf
  690. file, type "USE filename INDEX indexname" then press F6 (DISPLAY
  691. STATUS) to show the file in use.  Note that the .ndx file's name and
  692. key fields are also shown.  Do a screen print or "DISPLAY STATUS TO
  693. PRINT" and tape the index file info to the printout of the .dbf file
  694. structure.  This process is actually quite easy.
  695.      Remember to back up any related .mem and .dbt files along with the
  696. above.  To quote Macpherson's Law: "Murphy's Law is too optimistic.".
  697. - - - - -
  698.  
  699. dBASE III notes .009                         April 30, 1985
  700.  
  701. This week's note concerns the "&" and the "*"
  702.  
  703.      & is the dBASE MACRO FUNCTION. It looks like an ampersand (because
  704. it is!) and works in ways that new dBASE programmers sometimes have a
  705. lot of trouble figuring out.  First try the program below.  It's short
  706. but it illustrates the use of the "&" and also the asterisk or NOTE
  707. function:
  708.  
  709. **************** ASTERISK.prg
  710. *  demonstrates the "&" and the "*"
  711. ****************
  712.  
  713. a = "*"
  714.  
  715. ? "a" + "&a"
  716.  
  717. &a ? "This is line 1"
  718.  
  719. a = ""
  720.  
  721. &a ? "This is line 2"
  722.  
  723. If the keyword (NOTE) or the asterisk symbol appears in the first
  724. column of a line, dBASE ignores the rest of the line.  Same as the REM
  725. keyword or the apostrophe does in many versions of BASIC.  When you run
  726. ASTERISK.prg this is what takes place:
  727.      1 - the variable "a" is set equal to an asterisk.
  728.      2 - the first print statement prints an "a" and then "the contents
  729.          of a".  If you think of the "&" symbol as "the contents of" it
  730.          may help you see what is taking place.  Therefore, since "the
  731.          contents of a" is an asterisk, that's what appears on the
  732.          screen.
  733.      3 - in the next line the first expression is &a.  Since the & is
  734.          the "contents of " function, the computer looks for its
  735.          argument "a", sees it is an asterisk and puts that character
  736.          first on the line.  Seeing an asterisk first on a line causes
  737.          the computer to see the line as a comment and ignore it!
  738.      4 - "a" is "nulled out", that is, "a" is set equal to null - the
  739.          empty string.
  740.      5 - nearly the same line as before except that "a" is no longer
  741.          an asterisk but a null, so the "?" or print statement is
  742.          executed.
  743. The program's output?  Here it is:
  744.  
  745.      do asterisk
  746.      a*
  747.      This is line 2
  748.      .
  749.  
  750.      Try the program with other values for a such as *fGHY67 and 1234.
  751. Expect and interpret different results and error messages.  When you
  752. are comfortable with &, use it in other dBASE statements such as:
  753.  
  754. SET FILTER TO fieldname = "&variable"
  755. LOCATE FOR fieldname = "&variable"
  756.  
  757. and all those other places that "the contents of" a variable are
  758. needed.
  759.      See notes .003 and .005 for examples of other uses of the &
  760. function.
  761. - - - - -
  762.  
  763. dBASE III notes .010                         May 21, 1985
  764.  
  765. This week's note concerns DO, IF, SUM and "&" macro substitution.  It
  766. started innocently with a program as outlined below containing a DO
  767. WHILE and an IF statement, like this:
  768.  
  769. * FOO.prg
  770. * or how to find a bug in dBASE III v1.1
  771.  
  772. * Initialize some variables
  773.  
  774. date = CTOD("01/01/01")
  775.  
  776. * these are all date field names
  777. f1 = "FIELD1"
  778. f2 = "B->FIELD2"
  779.  .
  780.  .
  781.  .
  782. f28 = "FIELD28"
  783.  
  784. * open the files
  785. SELECT 1
  786.   USE FILENO1
  787. SELECT 2
  788.   USE FILENO2
  789. * link the two files by record no. since there are many fields
  790. SELECT 1
  791.   SET RELATION TO RECNO() INTO FILENO2
  792.  
  793. * cause the problems
  794.  
  795. GO TOP
  796. DO WHILE .NOT. EOF()
  797.   IF &f1>date .AND..NOT.(&f23<date.OR.&f24<date.OR.;
  798.        ........OR.&f28<date)
  799.     SUM fieldname TO total FOR &f1>date .AND..NOT.(&f20<date.OR.;
  800.         .........&f19<date.OR.&f18<date)
  801.   ENDIF
  802. ENDDO
  803.  
  804. ? "Title of the sum = "
  805.   ?? total
  806.  .
  807.  .
  808.  .
  809. etc
  810.  
  811. Anyway, I hope you get the idea: an IF statment inside a DO loop, each
  812. with a looooong qualifying clause of the Boolean persuasion.
  813.      When I tried to run the program, it executed fine until it hit the
  814. first record to fail the IF test.  Then the dot prompt appeared without
  815. any error message and without executing the print statement following
  816. the DO WHILE!  It was as though the CANCEL command had been executed,
  817. but at least with CANCEL you get a message like "DO cancelled".  So the
  818. debugging began.
  819.      First, there is a limit on line length. 254 characters.  It was
  820. possible that the expansions caused by the macros might have created a
  821. line longer than 254 characters (true for most command lines in dBASE).
  822. So, shorten the line.  Same problem.  Less than 254 characters for
  823. sure.  Now what?
  824.      Second, they admitted that use of a PUBLIC variable in a SUM
  825. statement can cause incorrect summing.  So I eliminated all PUBLIC
  826. variables in the program (Well, there were a few things I didn't tell
  827. you, but they didn't make any difference).  No improvement.
  828.      Then I copy the .prg file to FOO.prg and start eliminating
  829. statements and pieces of statements, a debugging technique I use when
  830. everything else has failed.
  831.      The first thing out was one of the macro substitutions in the SUM
  832. statement.  The program ran perfectly.  Flushed with success, I made
  833. the same change to the original program.  It failed.
  834.      I went back to foo, put the macro back into the SUM statement and
  835. it ran perfectly!
  836.      Checked the file for corrupted data. Everything fine.
  837.      It still bothered me that with TALK ON, the IF statement was the
  838. last line executed before the message-free exit from the program
  839. occurred.  I reexamined the program logic and decided I could do the
  840. job perfectly well without the IF or DO statements by suitably
  841. modifying the SUM statement.  All the macro substitutions went into a
  842. large SUM statement.  I got the answers about the data I needed for the
  843. report and had no more unexpected halts occur in the program.
  844.      About all I can conclude from this exercise is that there IS a bug
  845. which allows dBASE to exit a loop - back to the dot prompt - without
  846. any hint as to why.  I also confess to ignorance.  Anyway, if you
  847. happen across anything like this, call or write.
  848.      As to another similar occurrence with v1.0, that is, mysterious
  849. and inconclusive, see one of my earlier notes.
  850. - - - - -
  851.  
  852. dBASE III notes .011                         May 23, 1985
  853.  
  854. This week's note concerns INDEX, $ and debugging.
  855.  
  856. INDEX...
  857.      is the slickest way to make a file appear as though it was sorted
  858. even if it was not.  Using:
  859.  
  860. INDEX ON fieldname list TO indexfilename
  861.  
  862. is a neat, fast way to organize data items to reduce print time or the
  863. time to recall or add data to a file.  One of the problems appears in
  864. the latter area.  Let's use a fictitious example program to illustrate.
  865.      First suppose you have created the file FOO.dbf containing the
  866. imaginative fieldnames of FIELD1, FIELD2, ... FIELD30.  Then you have
  867. entered data and now issue the command:
  868.  
  869. INDEX ON FIELD1 + FIELD3 + FIELD22 TO FOO
  870.  
  871. This statement creates the index file known as FOO.ndx which, when in
  872. use, makes the file appear sorted on the key FIELD1 and then the sub-
  873. keys FIELD3 and FIELD22.  For example, if FIELD1 is the State and
  874. FIELD3 is the City, then the data will appear in State order and within
  875. each group of States it will appear sorted on the City, etc.
  876.      From here on whenever you USE FOO, it will appear in the order you
  877. entered the data.  If you USE FOO INDEX FOO, when you EDIT, SKIP or
  878. otherwise step through the file the data will appear as though it was
  879. sorted on the three "key fields" above: FIELD1, FIELD3 and FIELD22.
  880.      How do you keep the index file updated and if you add data to any
  881. of the KEY fields (1, 3 or 22 above), when will the index file be
  882. updated?  As usual in programming, there isn't one simple answer.  Here
  883. are some ways - maybe you can think of others:
  884.  
  885. 1. USE FOO
  886.    ...add/edit data...
  887.    SET INDEX TO FOO
  888.    REINDEX
  889.  
  890. 2. USE FOO INDEX FOO
  891.    add data..
  892.    (reindexing automatically done)
  893.  
  894. In short, if you update while the index is not in use, you will need to
  895. REINDEX afterward, while using the index file.  If the index file is in
  896. use, it is automatically updated.
  897.      So far so good.  How about creating another index file for
  898. FOO.dbf?  Let's say you do this:
  899.  
  900. USE FOO
  901. INDEX ON FIELD17 + FIELD2 TO FOO2
  902.  
  903. Now you've got two index files for the same data file - FOO.ndx and
  904. FOO2.ndx.  How can these both be updated quickly?  If you try it,
  905. REINDEX can be slow, especially if the number of key fields is large.
  906. A quicker way is to use one of the SET commands:
  907.  
  908. USE FOO
  909. SET INDEX TO FOO2, FOO
  910.  
  911. This statement makes the file appear as though it is sorted on the keys
  912. in FOO2.  FOO is along for the ride in that regard (read: doesn't do
  913. anything but is in use), but it is now also updated automatically
  914. whenever any of its key fields are changed.  No reindexing needed.
  915.      One caveat: be sure to pay attention to the manual's remarks about
  916. mass updates to key fields.  If you do it wrong, you can lose large
  917. chunks of data!
  918.      Read the section in the manual about SET while you're at it.
  919. There are quite a few handy items there, not only for indexing but
  920. also for relating one file to another either by record number or key
  921. field, setting printer margin, paths and so on...
  922.  
  923. $...
  924.      is the substring search function.  The only reason I mention it
  925. here is due to an old habit of naming string or dollar amount variables
  926. with the "$" character somewhere in the name.  Such as graph$, amount$
  927. or similar.  Well this old habit started when I was learning BASIC and
  928. dies hard.
  929.      Interestingly, filenames like fn$ and the like work fine.  So do
  930. the variable names like amount$.  When I tried to get a little fancier
  931. and wrote "app$tot" as a variable name, I got caught.  I've forgotten
  932. the specific error message, but you'll recognize it if you see it.  In
  933. short watch out for using special characters in your variable names.
  934. If you use "&" in one, you won't get any sympathy from me at all.
  935.  
  936. DEBUGGING...
  937.      is an art as well as a science.  It is estimated to take about 20%
  938. or more of the time involved in writing a well-planned program where
  939. the planning takes 50% of the time.  For those who like to "sit down at
  940. the piano and play" with only an overall idea of the objectives of the
  941. software, debugging percentages can approach 100%.
  942.      Some useful techniques to use are TALK, STEP, PUBLIC, CANCEL,
  943. DEBUG and ECHO.  Here is a short look at how each might be used:
  944.  
  945. SET TALK ON
  946.  
  947. is probably the most generally useful technique.  When issued as a
  948. command in the .prg file (or from the dot prompt if the .prg file
  949. doesn't SET TALK OFF and cancel that command), you can see the result
  950. of each line of the program printed on the screen (or the printer if
  951. you have SET PRINT ON).  If a value of a variable is changed, it will
  952. be printed.
  953.      When the error you are looking for occurs, you can tell which line
  954. is being executed (usually) and what the values of the most recently
  955. set variables are.  Often, the value causing the problem may be set in
  956. another line somewhere earlier.
  957.  
  958. PUBLIC...
  959.      can be used to examine the variable values if the error you are
  960. chasing causes the program to stop and the dot prompt to appear, or if
  961. you press Escape. If you then press F7 (display memory), and none of
  962. the variables have been declared public, no values will appear.  So to
  963. use PUBLIC, put the statement at the beginning of your command file
  964. like this:
  965.  
  966. PUBLIC variable list
  967.  
  968. and then F7 will give you their latest values.  One caution about this
  969. technique: if your bug is in a SUM statement, find another way to
  970. debug!  As noted in the previous note (#10), PUBLIC and SUM may not get
  971. along too well together.
  972.  
  973. STEP...
  974.      will allow the program to be executed one line at a time.  If you 
  975. need to stop the program after each line:
  976.  
  977. SET STEP ON
  978.  
  979. will do it.  You'll be asked to press a key after each line of the
  980. program has executed.  Useful for errors that can't be pinpointed to
  981. a particular line if the program isn't printing or if it's going too
  982. fast through a segment of the code for you to stop it easily.  Issue
  983. the command either from within a program if you don't want the thing
  984. to ask you to press enter for every step before a certain point, or
  985. from the dot prompt if you do.
  986.  
  987. CANCEL...
  988.      will stop the program and put you back to the dot prompt from any
  989. place within a command file.  It acts like a breakpoint in an assembly
  990. language program by letting you choose where to stop execution.  If you
  991. use PUBLIC in the same program, the values of the variables will then
  992. be available at that line for you to examine.
  993.  
  994. ECHO...
  995.      is a little like TALK, except where TALK displays the values of
  996. any variables that change, ECHO displays (or prints) the command(s)
  997. that are executed.
  998.  
  999. DEBUG...
  1000.      is handy for directing the output of the ECHO command to the
  1001. printer instead of the screen if you want to keep the screen from being
  1002. cluttered or overwritten while you are debugging.
  1003.      All of the above SET commands are described in the manual,
  1004. sometimes even in more detail.
  1005.      The above hints are really only tools for debugging provided in
  1006. the dBASE III programming language.  The most important one is located
  1007. between your ears.
  1008.      In the above debugging comments, various ways of employing these
  1009. tools were mentioned.  Now let's take a look at a few circumstances
  1010. where you might want them.
  1011.      After you have planned and written a program, the next step will
  1012. be to execute it.  Print reports, add data, enter data or make
  1013. calculations, for example.  This is the sequence:
  1014.      1. Plan the program logic
  1015.      2. Break the logic into steps of smaller size.
  1016.      3. Do step 2 until each step is (almost) a small enough segment
  1017.         to be coded directly from the logic.
  1018.      4. Write the code.
  1019.      5. Execute the code.
  1020.      6. Debug the code.
  1021.      Steps 1-3 usually take 50% of the programming time.  Step 4 can
  1022. then be done in about 10% of the time.  Step 6 consists of several
  1023. discrete kinds of operations:
  1024.      1. Syntax error checking.
  1025.      2. Running test data.
  1026.      3. Logic error checking.
  1027.  
  1028. SYNTAX ERRORS...
  1029.      are usually the simplest kind of errors to correct.  In most
  1030. cases, the program will halt and an error message is printed.  For most
  1031. errors in dBASE III, a question mark will appear just to the right of
  1032. the actual error.  Then you correct the error and run again.  Until
  1033. there aren't any more syntax error messages.  You might think that is
  1034. that.  Well, as you have by now guessed, there's a lot more.
  1035.      There are some errors that could be considered either syntax or
  1036. logic errors that won't give you any message.  For example, if you open
  1037. file FOO in area 1 and GOO in area 2 and then try to GET FIELD2 from
  1038. area 1 while you are in area 2.  You forgot that you were in the wrong
  1039. area and should have written GET A->FIELD2.  In this case, the screen
  1040. position where the result of the GET should have displayed will be
  1041. blank.  It is easy to think "there wasn't anything in the field in that
  1042. record, so the blank is OK".  The blank is NOT OK - it's an error.
  1043.      Thus you want to develop the habit of (at least mentally)
  1044. questioning every item that is printed by your code.  A blank may or
  1045. may not really be a blank...
  1046.  
  1047. RUN TEST DATA...
  1048.      The next important step in debugging is to run some test data.
  1049. Make sure you know in advance what the output will be.  Try to run data
  1050. at both ends and the middle of your data range.  For example, if your
  1051. program accepts data between $40 and $4 million for a variable value,
  1052. use both of these and several intermediate ones even if the usage of
  1053. the extremes is rare.  Then check the results by hand.
  1054.  
  1055. LOGIC ERRORS...
  1056.      may be much easier to spot if you run test data.  Wrong answers
  1057. may show them (or may show errors in your hand calculations) much more
  1058. efficiently than having your boss question them later at an inopportune
  1059. moment.  Other logic errors may show up in printing. Usually obviously.
  1060. The sneakier kind are those that may show up in selection logic, for
  1061. example:
  1062.  
  1063. COUNT FOR YEAR(FIELD3)>0.AND.FIELD16<56.OR.FIELD2<variable TO a
  1064.  
  1065. Here the Boolean logic should be assembled correctly so that "what you
  1066. THOUGHT you told the computer to do IS ACTUALLY what you told the
  1067. computer to do".
  1068.      Parentheses would make the above COUNT statement clearer or change
  1069. its meaning entirely.
  1070.